/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.ipti.br.tag.dao;

import java.util.ArrayList;
import org.ipti.br.tag.entity.Discipline;
import org.ipti.br.tag.entity.Discipline_;
import org.ipti.br.tag.entity.Unity;
import org.ipti.br.tag.entity.UnitySchedule;
import org.ipti.br.tag.entity.UnitySchedule_;
import org.ipti.br.tag.entity.Unity_;
import org.ipti.br.tag.entity.enums.WeekDay;
import java.util.Calendar;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 *
 * @author israel
 */
@Stateless
public class UnityScheduleFacade extends AbstractFacade<UnitySchedule> {

    @PersistenceContext(unitName = "TAG2PU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public UnityScheduleFacade() {
        super(UnitySchedule.class);
    }

    @Override
    public void create(UnitySchedule unitySchedule) {
        getEntityManager().persist(unitySchedule);
    }

    @Override
    public void edit(UnitySchedule unitySchedule) {
        getEntityManager().merge(unitySchedule);
    }

    public List<UnitySchedule> find(Unity unity, WeekDay weekDay) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<UnitySchedule> cq = cb.createQuery(UnitySchedule.class);
        Root<UnitySchedule> from = cq.from(UnitySchedule.class);
        Predicate p1 = cb.equal(from.join(UnitySchedule_.unity).get(Unity_.id), unity.getId());
        Predicate p3 = cb.equal(from.get(UnitySchedule_.weekDay), weekDay);

        cq.where(cb.and(p1,p3));
        try {
            return getEntityManager().createQuery(cq).getResultList();
        } catch (NoResultException nre) {
            return null;
        }
    }

    public List<UnitySchedule> find(Unity unity, WeekDay weekDay, Discipline discipline) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<UnitySchedule> cq = cb.createQuery(UnitySchedule.class);
        Root<UnitySchedule> from = cq.from(UnitySchedule.class);
        Predicate p1 = cb.equal(from.join(UnitySchedule_.unity).get(Unity_.id), unity.getId());
        Predicate p2 = cb.equal(from.join(UnitySchedule_.discipline).get(Discipline_.id), discipline.getId());
        Predicate p3 = cb.equal(from.get(UnitySchedule_.weekDay), weekDay);

        cq.where(cb.and(p1,p2,p3));
        try {
            return getEntityManager().createQuery(cq).getResultList();
        } catch (NoResultException nre) {
            return null;
        }
    }
    
    public List<Long> AulasPorDiaDaSemana(Unity unity){
        try{
            List<Long> workDayList = new ArrayList<Long>();
            Long[] day = new Long[7];
            List<Object[]> queryList = (List<Object[]>) em.createNativeQuery("select week_day, count(week_day) from unityschedule where unity_id = "+unity.getId()+" group by week_day").getResultList();
            for (Object[] o: queryList){
                day[(Integer) o[0]] = (Long) o[1];
            }
            for(int i = 0; i < day.length; i++){
                if(day[i] == null){
                    workDayList.add(0L);
                }else{
                    workDayList.add(day[i]);
                }
            }
            return workDayList;
        }catch(Exception e){
            System.out.println("pau");
            return new ArrayList<Long>();
        }
    }

    public List<UnitySchedule> unityScheduleGivenUnityWeekday(Long unityID, WeekDay weekday) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<UnitySchedule> cq = cb.createQuery(UnitySchedule.class);
        Root<UnitySchedule> from = cq.from(UnitySchedule.class);
        cq.where(cb.and(cb.equal(from.join(UnitySchedule_.unity).get(Unity_.id), unityID),
                cb.equal(from.get(UnitySchedule_.weekDay), weekday)));

        try {
            return getEntityManager().createQuery(cq).getResultList();
        } catch (NoResultException nre) {
            return null;
        }
    }

    public List<WeekDay> listWeekdays(Unity unity, Discipline discipline) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<WeekDay> cq = cb.createQuery(WeekDay.class);
        Root<UnitySchedule> rt = cq.from(UnitySchedule.class);
        cq.select(rt.get(UnitySchedule_.weekDay));
        
        Predicate p = cb.equal(rt.get(UnitySchedule_.unity).get(Unity_.id), unity.getId());
        if(discipline != null){
            p = cb.and(p, cb.equal(rt.get(UnitySchedule_.discipline).get(Discipline_.id), discipline.getId()));
        } else {
            cq.distinct(true);
        }
        
        cq.where(p);

        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<UnitySchedule> listForWeekdays(Unity unity, Discipline discipline) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<UnitySchedule> cq = cb.createQuery(UnitySchedule.class);
        Root<UnitySchedule> rt = cq.from(UnitySchedule.class);
        
        Predicate p = cb.equal(rt.get(UnitySchedule_.unity).get(Unity_.id), unity.getId());
        if(discipline != null){
            p = cb.and(p, cb.equal(rt.get(UnitySchedule_.discipline).get(Discipline_.id), discipline.getId()));
        }
        
        cq.where(p);
        cq.orderBy(cb.asc(rt.get(UnitySchedule_.weekDay)),cb.asc(rt.get(UnitySchedule_.initialTime)));

        return getEntityManager().createQuery(cq).getResultList();
    }

    public List<UnitySchedule> modifiedPerfFreqBetweenDate(Calendar initialDate, Calendar finalDate, Long serialNumber) {
        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<UnitySchedule> cq = cb.createQuery(UnitySchedule.class);
        Root<UnitySchedule> from = cq.from(UnitySchedule.class);
        Predicate predicate1 = cb.notEqual(from.get(UnitySchedule_.serialNumber), serialNumber);
        Predicate predicate2 = cb.greaterThanOrEqualTo(from.get(UnitySchedule_.lastModified), initialDate);
        Predicate predicate3 = cb.lessThan(from.get(UnitySchedule_.lastModified), finalDate);
        cq.where(cb.and(predicate1, predicate2, predicate3));

        return getEntityManager().createQuery(cq).getResultList();
    }
}
